package com.mk.plugin.action;

import com.intellij.ide.IdeView;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.lang.ASTNode;
import com.intellij.lang.ecmascript6.psi.ES6ExportDefaultAssignment;
import com.intellij.lang.javascript.JavaScriptSupportLoader;
import com.intellij.lang.javascript.psi.JSCallExpression;
import com.intellij.lang.javascript.psi.JSObjectLiteralExpression;
import com.intellij.lang.javascript.psi.JSProperty;
import com.intellij.lang.javascript.psi.JSRecursiveWalkingElementVisitor;
import com.intellij.lang.javascript.psi.ecma6.TypeScriptExportAssignment;
import com.intellij.lang.javascript.psi.impl.JSChangeUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.mk.plugin.function.*;
import com.mk.plugin.generator.ActionGenerator;
import com.mk.plugin.generator.IndexGenerator;
import com.mk.plugin.generator.ReducerGenerator;
import com.mk.plugin.model.ToolbarComponentModel;
import com.mk.plugin.ui.StartSetting;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

public class NewPageInitAction extends AnAction {

    private static final Logger log = Logger.getInstance(NewPageInitAction.class);

    @Override
    public void actionPerformed(AnActionEvent e) {
        StartSetting dialog = new StartSetting(functionSettings -> {
            final DataContext dataContext = e.getDataContext();

            final IdeView view = LangDataKeys.IDE_VIEW.getData(dataContext);
            if (view == null) {
                return;
            }

            final Project project = PlatformDataKeys.PROJECT.getData(dataContext);

            final PsiDirectory dir = view.getOrChooseDirectory();
            if (dir == null || project == null) return;

            if (dir.getFiles().length == 0) {
                ApplicationManager.getApplication().runWriteAction(() -> {
                    String[] split = dir.getName().split("-");
                    String dashName = dir.getName();
                    String underscoreName = StringUtil.join(split, "_");
                    String firstUpperCamelCaseName = Arrays.stream(split).map((w) -> Character.toUpperCase(w.charAt(0)) + w.substring(1).toLowerCase()).collect(Collectors.joining());
                    String allUpperCaseUnderscoreName = underscoreName.toUpperCase();
                    String moduleName = "error";
                    String moduleNameCamelCase = "error";
                    String moduleUnderscoreName = "error";

                    // 初始化要用的Function列表
                    List<Functions> functionsList = ((List<ToolbarComponentModel>) functionSettings.get("toolbarComponentModelList")).stream().map(t -> {
                        switch (t.getType()) {
                            case "date range":
                                return new DateRangeFunction(t.getFieldName(), t.getLabelText());
                            case "search":
                                return new SearchInputFunction(t.getFieldName());
                            case "select":
                                return new SelectFunction(t.getFieldName(), t.getLabelText());
                            default:
                                return new DateRangeFunction(t.getFieldName(), t.getLabelText());
                        }
                    }).collect(Collectors.toList());

                    if (((Boolean) functionSettings.get("page"))) {
                        functionsList.add(new PageFunction(""));
                    }

                    PsiDirectory dirParent = null;
                    if (dir.getParent() != null) {
                        dirParent = dir.getParent().getParent();
                    }
                    if (dirParent != null) {
                        if (dirParent.getName().contains("tenantsManagePlatform_")) {
                            moduleName = dirParent.getName().substring("tenantsManagePlatform_".length());
                        } else {
                            moduleName = "purchasing-storage";
                        }
                        if (moduleName.contains("-")) {
                            String[] parts = moduleName.split("-");
                            StringBuilder camelCaseString = new StringBuilder();
                            for (int i = 0; i < parts.length; i++) {
                                String part = parts[i];
                                if (i != 0) {
                                    camelCaseString.append(part.substring(0, 1).toUpperCase()).append(part.substring(1).toLowerCase());
                                } else {
                                    camelCaseString.append(part);
                                }
                            }
                            moduleNameCamelCase = camelCaseString.toString();
                        } else {
                            moduleNameCamelCase = moduleName;
                        }
                        moduleUnderscoreName = StringUtil.join(moduleName.split("-"), "_");
                    }

                    Properties properties = new Properties();
                    properties.put("dashName", dashName);
                    properties.put("moduleName", moduleName);
                    properties.put("moduleNameCamelCase", moduleNameCamelCase);
                    properties.put("UpperPageName", firstUpperCamelCaseName);
                    properties.put("underscore_name", underscoreName);
                    properties.put("pageTitle", "请定义标题");
                    properties.put("allUpperCaseUnderscoreName", allUpperCaseUnderscoreName);
                    properties.put("listApiUrl", functionSettings.get("listApiUrl"));
                    if (((String) functionSettings.get("fieldListText")).length() > 0) {
                        String fieldListText = (String) functionSettings.get("fieldListText");
                        List<List<String>> collect = Arrays.stream(fieldListText.split(" ")).map(i -> Arrays.asList(i.split("\\|"))).collect(Collectors.toList());
                        properties.put("fieldList", collect);
                    }// 用户ID|userId 用户昵称|userName 手机号码|telephone 任务领取时间|takePartInTime 阅读次数|readTimes 状态|finishStatus 完成时间|finishTime 获得奖励|rewards

                    ActionGenerator actionGenerator = new ActionGenerator();
                    actionGenerator.generator(project, properties, dir, functionsList);

                    ReducerGenerator reducerGenerator = new ReducerGenerator();
                    reducerGenerator.generator(project, properties, dir, functionsList);

                    dir.createSubdirectory("components");

                    IndexGenerator indexGenerator = new IndexGenerator();
                    indexGenerator.generator(project, properties, dir, functionsList);

                    PsiFile moduleCssFile;
                    if (dirParent != null) {
                        for (PsiDirectory psiDirectory : dirParent.getSubdirectories()[0].getSubdirectories()) { // 处理sass文件，添加对应的sass文件，并且自动进行引入
                            if (psiDirectory.getName().equals("css")) {
                                for (PsiFile psiFile : psiDirectory.getFiles()) {
                                    if (psiFile.getName().endsWith("style.sass")) {
                                        FileTemplate styleTemplate = FileTemplateManager.getInstance(project).getInternalTemplate("style");
                                        try {
                                            FileTemplateUtil.createFromTemplate(styleTemplate, underscoreName + ".sass", properties, psiDirectory);
                                        } catch (Exception e1) {
                                            e1.printStackTrace();
                                        }
                                        moduleCssFile = psiFile;
                                        try {
                                            Files.write(Paths.get(moduleCssFile.getVirtualFile().getPath()), String.format("\n@import \"./%s\"", underscoreName).getBytes(), StandardOpenOption.APPEND);
                                            moduleCssFile.getVirtualFile().refresh(true, false);
                                        } catch (IOException e1) {
                                            e1.printStackTrace();
                                        }
                                        log.info("find module css file");
                                    }
                                }

                            }
                        }

                        for (PsiFile psiFile : dirParent.getSubdirectories()[0].getFiles()) {
                            if (psiFile.getName().equals(moduleUnderscoreName + ".reducers.tsx")) {
                                String finalModuleNameCamelCase = moduleNameCamelCase;
                                psiFile.accept(new JSRecursiveWalkingElementVisitor() {
                                    @Override
                                    public void visitES6ExportDefaultAssignment(ES6ExportDefaultAssignment exportDefaultAssignment) {
                                        log.info("find default export");
                                        exportDefaultAssignment.accept(new JSRecursiveWalkingElementVisitor() {
                                            @Override
                                            public void visitJSCallExpression(JSCallExpression node) {

                                                log.info(node.getMethodExpression().getText());
                                                if ("combineReducers".equals(node.getMethodExpression().getText())) {
                                                    if (node.getArgumentList() != null) {
                                                        node.getArgumentList().accept(new JSRecursiveWalkingElementVisitor() {
                                                            @Override
                                                            public void visitJSObjectLiteralExpression(JSObjectLiteralExpression jsObjectLiteralExpression) {
                                                                log.info("find export object");
                                                                JSProperty jsProperty = jsObjectLiteralExpression.getProperties()[jsObjectLiteralExpression.getProperties().length - 1];
                                                                ASTNode expressionWithContext =
                                                                        JSChangeUtil.createExpressionWithContext(
                                                                                "{" +
                                                                                        String.format("%s,", finalModuleNameCamelCase + firstUpperCamelCaseName + "Reducer") +
                                                                                        "}", jsObjectLiteralExpression);


                                                                ASTNode statementFromText = JSChangeUtil.createStatementFromText(project,
                                                                        String.format("import %s from './%s/reducers/%s.reducers'", finalModuleNameCamelCase + firstUpperCamelCaseName + "Reducer", dashName, underscoreName),
                                                                        JavaScriptSupportLoader.TYPESCRIPT_JSX, false);


                                                                if (expressionWithContext != null && statementFromText != null) {
                                                                    JSProperty newProperty = ((JSObjectLiteralExpression) expressionWithContext.getPsi()).getFirstProperty();
                                                                    PsiElement importElement = statementFromText.getPsi();

                                                                    if (newProperty != null && importElement != null) {
                                                                        WriteCommandAction.runWriteCommandAction(project, () -> {
                                                                            jsObjectLiteralExpression.addAfter(newProperty, jsProperty);
                                                                            PsiElement commaPsiElement = JSChangeUtil.createCommaPsiElement(project);
//                                                                            jsObjectLiteralExpression.addAfter(commaPsiElement, jsProperty);
                                                                            JSChangeUtil.addWs(jsObjectLiteralExpression.getNode(), jsProperty.getNode(), "");

                                                                            psiFile.addBefore(importElement, exportDefaultAssignment);
                                                                        });
                                                                    }
                                                                }
                                                            }


                                                        });
                                                    }
                                                }
                                            }
                                        });
                                    }
                                });

                                log.info("find module reducers file");

                            }
                        }
                    }

                });
            }
        });
        dialog.setSize(500, 400);
        dialog.setVisible(true);
    }

}
